#include <errno.h>
#include <limits.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/*
 * $ tcc -run - <<<"main(){printf(\"%*s\r%s\n$ \", $COLUMNS, \"Hello\", \"PS1\");}"
 */

/*
 * http://wiki.archlinux.org/index.php/Bash/Prompt_customization
 */

/*
 * http://bugs.python.org/issue20359
 * http://stackoverflow.com/questions/9468435/look-how-to-fix-column-calculation-in-python-readline-if-use-color-prompt
 * http://unix.stackexchange.com/questions/367485/using-echo-e-in-ps1-causes-line-break-issues-in-shell
 */
/* From readline.h: */
#define RL_PROMPT_START_IGNORE  '\001'
#define RL_PROMPT_END_IGNORE    '\002'

/*
 * http://en.wikipedia.org/wiki/ANSI_escape_code
 * http://www.linuxjournal.com/article/8603
 */
/* From terminfo(5): */
enum {
	COLOR_BLACK = 0,
	COLOR_RED,
	COLOR_GREEN,
	COLOR_YELLOW,
	COLOR_BLUE,
	COLOR_MAGENTA,
	COLOR_CYAN,
	COLOR_WHITE
};

/* Set foreground color using ANSI escape code */
static void
setaf(int color)
{
	putchar(RL_PROMPT_START_IGNORE);
	printf("\033[0;3%dm", color);
	putchar(RL_PROMPT_END_IGNORE);
}

/* Reset colors */
static void
sgr0(void)
{
	putchar(RL_PROMPT_START_IGNORE);
	printf("\033[0m");
	putchar(RL_PROMPT_END_IGNORE);
}

static int
cprintf(int color, const char *fmt, ...)
{
	va_list ap;
	int ret;

	setaf(color);

	va_start(ap, fmt);
	ret = vprintf(fmt, ap);
	va_end(ap);

	sgr0();

	return ret;
}

static char *
get_homedir(char *homedir, size_t homedir_size)
{
	struct passwd *pwd;

	errno = 0;
	pwd = getpwuid(getuid());
	if (errno) {
		perror("getpwuid");
		return NULL;
	}
	strncpy(homedir, pwd->pw_dir, homedir_size);

	endpwent();

	return homedir;
}

/*
 * s/^$HOME/~/ $PWD
 */
static char *
tilde_home(char *cwd, const char *homedir)
{
	size_t homedir_len = strlen(homedir);
	size_t i;

	if (strncmp(homedir, cwd, homedir_len)) {
		/* not in your own $HOME */
		return NULL;
	}

	cwd[0] = '~';
	for (i=1; cwd[homedir_len-1+i]; ++i) {
		cwd[i] = cwd[homedir_len-1+i];
	}
	cwd[i] = '\0';

	return cwd;
}

int
main(void)
{
	char cwd[PATH_MAX];
	const size_t cwd_size = PATH_MAX;
	char homedir[PATH_MAX];
	const size_t homedir_size = PATH_MAX;
	char *uname;
	char hostname[HOST_NAME_MAX+1];
	const size_t hostname_size = HOST_NAME_MAX+1; /* + '\0' */

	int ret;

	if (!getcwd(cwd, cwd_size)) {
		perror("getcwd");
	}
	if (!get_homedir(homedir, homedir_size)) {
		fputs("get_homedir error\n", stderr);
		exit(EXIT_FAILURE);
	}
	tilde_home(cwd, homedir);

	if (!(uname = getlogin())) {
		perror("getlogin");
	}

	if (gethostname(hostname, hostname_size)) {
		fputs("Couldn't get hostname.\n", stderr);
		exit(EXIT_FAILURE);
	}

	ret = printf("[%s@%s %s]\n", uname, hostname, cwd);
	fprintf(stderr, "%d\n", ret);
	ret = cprintf(COLOR_GREEN, "$ ");
	fprintf(stderr, "%d\n", ret);

	return 0;
}
